
#include<iostream>
#include<string>
#include<time.h>
#include<mutex>
#include<thread>
#include<fstream>

using namespace std;

#define LOGAPP logger::getinstance()

enum class loglevel: int{
        Debug = 0,
        Info = 1,
        Error = 2,
        Fatal = 3

    };  //用来标记日志等级


//单例类
class logger {
private:
    loglevel level; //用来标记日志等级
    string content; //文件内容
    string name; //日志文件名称
    static logger* instance;
    static mutex t_mutex;
    logger(){};
public: 
    ~logger()=delete;

    static logger* getinstance(){
        unique_lock<mutex> lock(t_mutex);
        if(instance!=NULL){
            return instance;
        }
        else{
            instance=new logger();
            return instance;
        }
    }

    string GetLevelStr(loglevel level);//根据level的值返回对应字符串
    void CreateLogFile(string s1,string s2,loglevel level);//创建日志文件

    string getsname() { return name; }
    void setsname(string sname){this->name=sname;};
    string getcontent() { return content; }
    void setcontent(string scontent) {this->content=scontent;};
    loglevel getLevel(){return level;}
    void setLevel(loglevel level){this->level=level;}

};

logger* logger::instance=NULL;
mutex logger::t_mutex;

string logger::GetLevelStr(loglevel level)
{   
    switch (level)
    {
    case loglevel::Debug:
        return "DEBUG";
    case loglevel::Info:
        return "INFO";
    case loglevel::Error:
        return "ERROR";
    case loglevel::Fatal:
        return "FATAL";
    default:
        return "UNKNOW";
    }
}


//创建日志文件
void logger::CreateLogFile(string s1,string s2,loglevel level) {
    ofstream out(s1,ios::app);  //避免覆盖原有内容
    if (out.is_open()) {
        out <<s2<< endl;
        out<<"the level is"<<GetLevelStr(level)<<endl;
        time_t rawtime;
        struct tm * timeinfo;
        timeinfo = localtime ( &rawtime );
        out<<"time:"<<asctime (timeinfo)<<endl;
        //cout<<"open a file"<<endl;
        out.close();
    }
    else {
        cout << "no such file" << endl;
    }
}


void writelog(){

    string s1=LOGAPP->getsname();
    string s2=LOGAPP->getcontent();
    loglevel level=LOGAPP->getLevel();
    LOGAPP->CreateLogFile(s1,s2,level);

}


int main() {
    
    string s1 = "log.txt"; string s2 = "this is a txt1";
    loglevel level=loglevel::Info;
    string s22="this is a test";

    LOGAPP->setsname(s1);
    LOGAPP->setcontent(s2);
    LOGAPP->setLevel(level);
   
    thread t1(writelog);
    t1.join();
    LOGAPP->setcontent(s22);
    thread t2(writelog);
    t2.join();

    return 0;
}